package org.cqust.backend.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.cqust.backend.common.ApiResult;
import org.cqust.backend.dto.request.auth.LoginRequest;
import org.cqust.backend.dto.request.auth.RegisterRequest;
import org.cqust.backend.dto.response.LoginDTO;
import org.cqust.backend.entity.User;
import org.cqust.backend.service.JwtService;
import org.cqust.backend.service.UserService;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    private final AuthenticationManager authenticationManager;
    private final JwtService jwtService;
    private final UserService userService;

    /**
     * 构造函数，初始化AuthController。
     *
     * @param authenticationManager 认证管理器实例
     * @param jwtService JWT服务实例
     * @param userService 用户服务实例
     */
    public AuthController(AuthenticationManager authenticationManager, JwtService jwtService, UserService userService) {
        this.authenticationManager = authenticationManager;
        this.jwtService = jwtService;
        this.userService = userService;
    }

    /**
     * 用户登录接口。
     *
     * @param request 包含用户名和密码的登录请求
     * @return 包含JWT令牌的ApiResult对象
     */
    @Operation(summary = "用户登录")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "登录成功"),
            @ApiResponse(responseCode = "400", description = "账号不存在或密码不匹配", content = @Content),
            @ApiResponse(responseCode = "500", description = "服务器内部错误", content = @Content)
    })
    @PostMapping("/login")
    public ApiResult<LoginDTO> login(@RequestBody LoginRequest request) {
        Authentication authentication;
        try {
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            request.getUsername(),
                            request.getPassword()
                    )
            );

        } catch (UsernameNotFoundException e) {
            return ApiResult.error("账号不存在");
        } catch (BadCredentialsException e) {
            return ApiResult.error("密码不匹配");
        } catch (Exception e) {
            return ApiResult.error(e.getLocalizedMessage());
        }

        UserDetails user = (UserDetails) authentication.getPrincipal();
        String jwtToken = jwtService.generateToken(user);
        // 更新最后登录时间
        User principal = (User) authentication.getPrincipal();
        Long userId = principal.getId();
        userService.updateLastLogin(userId);
        LoginDTO ret = new LoginDTO();
        ret.setRole(principal.getRole());
        ret.setUsername(principal.getUsername());
        ret.setToken(jwtToken);
        return ApiResult.success(ret);
    }

    /**
     * 用户注册接口。
     *
     * @param request 包含注册信息的请求
     * @return 包含注册结果的ApiResult对象
     */
    @Operation(summary = "用户注册")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "注册成功"),
            @ApiResponse(responseCode = "400", description = "注册失败", content = @Content),
            @ApiResponse(responseCode = "500", description = "服务器内部错误", content = @Content)
    })
    @PostMapping("/register")
    public ApiResult<String> register(@RequestBody RegisterRequest request) {
        try {
            userService.registerUser(request);
            return ApiResult.success("注册成功");
        } catch (DataIntegrityViolationException e) {
            return ApiResult.error("注册失败：已存在同名的账号");
        } catch (Exception e) {
            return ApiResult.error("注册失败: " + e.getLocalizedMessage());
        }
    }
}